/*
 * Funambol is a mobile platform developed by Funambol, Inc. 
 * Copyright (C) 2003 - 2007 Funambol, Inc.
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission 
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE 
 * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Affero General Public License 
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 * 
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite 
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 * 
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 * 
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably 
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */

#include "NoteSyncSource.h"
#include "spds/SyncStatus.h"
#include "base/Log.h"
NoteSyncSource::NoteSyncSource(SyncSourceConfig& sc, PIMDataStore& ds, PIMDataConverter& dc, ChangesTracker& ct):
SyncSource(sc.getName(), &sc){
    ssc = sc;
    ndc= (NoteDataConverter*)&dc;
    nds =(NoteDataStore*) &ds;
    nct = (NoteChangesTracker*)&ct; 
}

NoteSyncSource::~NoteSyncSource(){
}


/// Used to access configuration of SS
const SyncSourceConfig& NoteSyncSource::getConfig() const{ return ssc;}
SyncSourceConfig& NoteSyncSource::getConfig(){ return ssc;}

int NoteSyncSource::beginSync(){
    LOG.debug("NoteSync source: beginSync ");
    //int ret = nds->checkDBFunTable();
    return 0;
}

int NoteSyncSource::endSync(){
    LOG.debug("NoteSync source: EndSync ");
    nds->resetFlags( getNextSync() );
    return 0;
}

void NoteSyncSource::setItemStatus(const char* key, int status){
    
}

void NoteSyncSource::assign(NoteSyncSource& s){}
//int NoteSyncSource::removeAllItems() {return 0; }

SyncItem* NoteSyncSource::transformIntoSyncItem(const char* identifier, Note& n){
    SyncItem* s = new SyncItem(identifier);
    s->setData(ndc->format((PIMItem&)n), strlen(ndc->format((PIMItem&)n)));
    return s;
}

// --------- Methods to get syncItems from Client --------------
SyncItem* NoteSyncSource::getFirstItem(){
    LOG.debug("NoteSync source: getFirstItem ");
    nct->getAll();
    StringBuffer* identifier = nct->getNextId();
    if (identifier && !identifier->empty()){
        return transformIntoSyncItem(*identifier, (Note&)(*(nds->getPIMItem(*identifier))));
    }
    return NULL;
}

SyncItem* NoteSyncSource::getNextItem (){
    LOG.debug("NoteSync source: getNextItem  ");
    StringBuffer* identifier =  nct->getNextId();
    if (identifier && !identifier->empty()){
        return transformIntoSyncItem(*identifier, (Note&)(*(nds->getPIMItem(*identifier))));
    }
    return NULL;
}

SyncItem* NoteSyncSource::getFirstNewItem(){
    LOG.debug("NoteSync source: getFirstNewItem ");
    nct->getModifications(ssc.getLast());
    StringBuffer* identifier = nct->getNextNewId();
    if (identifier && !identifier->empty()){
        return transformIntoSyncItem(*identifier, (Note&)(*(nds->getPIMItem(*identifier))));
    }
    return NULL;
    
}

SyncItem* NoteSyncSource::getNextNewItem (){
    LOG.debug("NoteSync source: getNextNewItem");
    StringBuffer* identifier = nct->getNextNewId();
    
    if (identifier && !identifier->empty()){
        return transformIntoSyncItem(*identifier, (Note&)(*(nds->getPIMItem(*identifier))));
    }
    return NULL;
}

SyncItem* NoteSyncSource::getFirstUpdatedItem(){
    LOG.debug("NoteSync source: getFirstUpdatedItem ");
    StringBuffer* identifier = nct->getNextUpdateId();
    
    if (identifier && !identifier->empty()){
        return transformIntoSyncItem(*identifier, (Note&)(*(nds->getPIMItem(*identifier))));
    }
    return NULL;
}

SyncItem* NoteSyncSource::getNextUpdatedItem (){
    LOG.debug("NoteSync source: getNextUpdatedItem ");
    StringBuffer* identifier = nct->getNextUpdateId();
    
    if (identifier && !identifier->empty()){
        return transformIntoSyncItem(*identifier, (Note&)(*(nds->getPIMItem(*identifier))));
    }
    return NULL;
}

SyncItem* NoteSyncSource::getFirstDeletedItem(){
    LOG.debug("NoteSync source: getFirstDeletedItem");
    StringBuffer* identifier = nct->getNextDeleteId();
    
    if (identifier && !identifier->empty()){
        return new SyncItem(identifier->c_str());
    }
    return NULL;
    
}

SyncItem* NoteSyncSource::getNextDeletedItem (){
    LOG.debug("NoteSync source: getNextDeletedItem");
    StringBuffer* identifier = nct->getNextDeleteId();
    
    if (identifier && !identifier->empty()){
        return new SyncItem(identifier->c_str());
    }
    return NULL;
}

SyncItem* NoteSyncSource::getFirstItemKey(){
    return NULL;
}
SyncItem* NoteSyncSource::getNextItemKey(){
    return NULL;
}


// --------- Methods to set syncItems into Client --------------
int NoteSyncSource::addItem   (SyncItem& item){
    LOG.debug("NoteSync source: addItem");
    StringBuffer tmp;
	int ret = STC_COMMAND_FAILED;
    PIMItem* n = ndc->parse((const char*)item.getData());
    if (nds->addPIMItem(tmp, *n) == 0) {        
	    item.setKey(tmp.c_str());
        ret = STC_ITEM_ADDED;
        LOG.debug("Added item %s", tmp.c_str());
	} else {
        LOG.error("Add item %s error", (const char*)item.getData());
	}
    return ret;
}

int NoteSyncSource::updateItem(SyncItem& item){
    LOG.debug("NoteSync source: updateItem");
	int ret = STC_COMMAND_FAILED;
    PIMItem* n = ndc->parse((const char*)item.getData());
	if (nds->updatePIMItem(item.getKey(), *n) == 0) {
        ret = STC_OK;
	    LOG.debug("Updated item %s", item.getKey());	    
	} else {
	    LOG.error("Updated item %s error", item.getKey());
	}
	return ret;
}

int NoteSyncSource::deleteItem(SyncItem& item){
    LOG.debug("NoteSync source: deleteItem");
	int ret = STC_COMMAND_FAILED;
	if (nds->deletePIMItem(item.getKey()) == 0) {
        ret = STC_OK;
	    LOG.debug("Deleted item %s", item.getKey());
	} else {
        LOG.error("Deleted item %s error", item.getKey());
    }
    return ret;
    
}

int NoteSyncSource::removeAllItems(){

    nct->getAll();
    StringBuffer* val = nct->getNextId();
    int ret = 0 ;
    while (val) {
        if (nds->deletePIMItem(val->c_str()) == 0) {
            ret = STC_OK;
            LOG.debug("Deleted item %s", val->c_str());
        } else {
            LOG.error("Deleted item %s error", val->c_str());
        }
        val = nct->getNextId();
    }
    delete val;
    setLastAnchor("");
    setNextAnchor("");
    ssc.setLast(0);

    
    return ret;
}
